package elevation.general;

import java.io.IOException;
import java.io.InputStream;
import java.util.List;

import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.protocol.BasicHttpContext;
import org.apache.http.protocol.HttpContext;

import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.graphics.drawable.Drawable;
import android.location.Address;
import android.location.Geocoder;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.net.NetworkInfo.State;
import android.os.Bundle;
import android.os.CountDownTimer;
import android.provider.Settings;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.ImageButton;

import com.google.android.maps.GeoPoint;
import com.google.android.maps.MapController;

import elevation.general.balloon.CustomItemizedOverlay;
import elevation.general.balloon.CustomOverlayItem;
import elevation.general.utils.OnSingleTapListener;
import elevation.general.utils.TapControlledMapView;

public class ElevationActivity extends BaseActivity {
	private TapControlledMapView mMapView;
	private MapController mMapController;
	private LocationManager mLocationManager;
	private boolean mStopTimer;
	private Location mLocation;
	private double resultMeters = Double.NaN;
	private double resultFeet = Double.NaN;
	private boolean mFirstStart;
	private ImageButton mReloadButton;
	private ImageButton mCalcolaButton;
	private ImageButton mFbButton;
	private static String tagOpenElevation = "<elevation>";
	private static String tagCloseElevation = "</elevation>";
	private static String tagOpenLat = "<lat>";
	private static String tagCloseLat = "</lat>";
	private static String tagOpenLng = "<lng>";
	private static String tagCloseLng = "</lng>";

	// private TextView mTextAltimeter;

	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.main);

		mResume = false;

		// mTextAltimeter = ((TextView) findViewById(R.id.text_altimeter));

		mMapView = (TapControlledMapView) findViewById(R.id.maps);
		mMapView.setBuiltInZoomControls(true);
		mMapController = mMapView.getController();

		mMapView.setOnSingleTapListener(new OnSingleTapListener() {
			@Override
			public boolean onSingleTap(MotionEvent e) {
				// itemizedOverlay.hideAllBalloons();
				return true;
			}
		});

		setupLocationManager(false);

		mCalcolaButton = (ImageButton) findViewById(R.id.calcola_button);
		mCalcolaButton.setOnClickListener(new OnClickListener() {

			@Override
			public void onClick(View v) {
				ConnectivityManager conMan = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);

				// mobile
				State mobile = conMan.getNetworkInfo(ConnectivityManager.TYPE_MOBILE).getState();

				// wifi
				State wifi = conMan.getNetworkInfo(ConnectivityManager.TYPE_WIFI).getState();

				if (mobile == NetworkInfo.State.CONNECTED || mobile == NetworkInfo.State.CONNECTING
						|| wifi == NetworkInfo.State.CONNECTED || wifi == NetworkInfo.State.CONNECTING) {
					Thread t = new Thread(new Runnable() {

						@Override
						public void run() {
							getElevationFromGoogleMaps(mMapView.getMapCenter().getLatitudeE6() / (1E6), mMapView
									.getMapCenter().getLongitudeE6() / (1E6));

						}
					});
					t.start();

				} else {
					new AlertDialog.Builder(ElevationActivity.this).setIcon(android.R.drawable.ic_dialog_alert)
							.setTitle(R.string.warning).setMessage(R.string.check_network)
							.setPositiveButton("Ok", new DialogInterface.OnClickListener() {

								@Override
								public void onClick(DialogInterface dialog, int which) {
								}

							}).show();
				}

			}
		});

		mReloadButton = (ImageButton) findViewById(R.id.reload_position);
		mReloadButton.setOnClickListener(new OnClickListener() {

			@Override
			public void onClick(View v) {
				// drawIcon();
				setupLocationManager(true);
			}
		});

		mFbButton = (ImageButton) findViewById(R.id.fb_button);
		mFbButton.setOnClickListener(new OnClickListener() {

			@Override
			public void onClick(View v) {

				new AlertDialog.Builder(ElevationActivity.this).setIcon(android.R.drawable.ic_dialog_alert)
						.setTitle(R.string.warning).setMessage(R.string.facebook_alert)
						.setPositiveButton(getString(R.string.yes), new DialogInterface.OnClickListener() {

							@Override
							public void onClick(DialogInterface dialog, int which) {

								if (mLocation != null) {
									Thread t = new Thread(new Runnable() {

										@Override
										public void run() {
											getElevationFromGoogleMapsMod(mLocation.getLatitude(),
													mLocation.getLongitude());

										}
									});
									t.start();
								}
							}

						}).setNegativeButton("No", new DialogInterface.OnClickListener() {

							@Override
							public void onClick(DialogInterface dialog, int which) {
								dialog.dismiss();
							}
						}).show();
			}
		});

	}

	// private void setText() {
	// ((TextView)
	// findViewById(R.id.text_altimeter)).setText(String.valueOf(resultMeters).substring(0,
	// String.valueOf(resultMeters).indexOf(".") + 2)
	// + " "
	// + getString(R.string.meters)
	// + " | "
	// + String.valueOf(resultFeet).substring(0,
	// String.valueOf(resultFeet).indexOf(".") + 2)
	// + " "
	// + getString(R.string.feets));
	// }

	private void setupLocationManager(boolean fromReload) {
		mStopTimer = false;
		mLocationManager = (LocationManager) this.getSystemService(Context.LOCATION_SERVICE);
		if (mLocationManager.isProviderEnabled(LocationManager.GPS_PROVIDER)) {
			showProgressAsync();
			mLocationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, mLocationListenerNetwork);

			new CountDownTimer(30000, 1000) {

				public void onTick(long millisUntilFinished) {
				}

				public void onFinish() {
					mLocationManager.removeUpdates(mLocationListenerNetwork);
					hideProgressAsync();
					if (!mStopTimer) {
						mStopTimer = true;
						new AlertDialog.Builder(ElevationActivity.this).setIcon(android.R.drawable.ic_dialog_alert)
								.setTitle(R.string.warning).setMessage(R.string.localization_gps)
								.setPositiveButton(getString(R.string.yes), new DialogInterface.OnClickListener() {

									@Override
									public void onClick(DialogInterface dialog, int which) {
										networkListener();
										dialog.dismiss();
									}

								}).setNegativeButton("No", new DialogInterface.OnClickListener() {

									@Override
									public void onClick(DialogInterface dialog, int which) {
										setupLocationManager(false);
										dialog.dismiss();
									}
								}).show();
					}
				}
			}.start();
		} else {
			if (fromReload) {
				networkListener();
			} else {
				new AlertDialog.Builder(this).setIcon(android.R.drawable.ic_dialog_alert).setTitle(R.string.warning)
						.setMessage(R.string.localization_gps_disable)
						.setPositiveButton("Ok", new DialogInterface.OnClickListener() {

							@Override
							public void onClick(DialogInterface dialog, int which) {
								startActivity(new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS));
							}

						}).show();
			}
		}
	}

	LocationListener mLocationListenerNetwork = new LocationListener() {

		public void onLocationChanged(Location location) {
			mLocation = location;
			mLocationManager.removeUpdates(this);
			drawIcon();
			mStopTimer = true;
		}

		public void onProviderDisabled(String provider) {
		}

		public void onProviderEnabled(String provider) {
		}

		public void onStatusChanged(String provider, int status, Bundle extra) {
		}

	};
	private boolean mResume;
	private MenuItem mSatView;
	private MenuItem mStreetView;

	private void getElevationFromGoogleMaps(final double longitude, final double latitude) {
		showProgressAsync();

		HttpClient httpClient = new DefaultHttpClient();
		HttpContext localContext = new BasicHttpContext();
		String url = "http://maps.googleapis.com/maps/api/elevation/" + "xml?locations=" + String.valueOf(longitude)
				+ "," + String.valueOf(latitude) + "&sensor=true";
		HttpGet httpGet = new HttpGet(url);
		try {
			HttpResponse response = httpClient.execute(httpGet, localContext);
			HttpEntity entity = response.getEntity();
			if (entity != null) {
				final InputStream instream = entity.getContent();
				int r = -1;
				final StringBuffer respStr = new StringBuffer();
				while ((r = instream.read()) != -1)
					respStr.append((char) r);

				mHandler.post(new Runnable() {
					public void run() {

						if (respStr.indexOf(tagOpenElevation) != -1) {
							int start = respStr.indexOf(tagOpenElevation) + tagOpenElevation.length();
							int end = respStr.indexOf(tagCloseElevation);
							String value = respStr.substring(start, end);
							resultMeters = (double) (Double.parseDouble(value));
							resultFeet = (double) (Double.parseDouble(value) * 3.2808399);

							Geocoder coder = new Geocoder(ElevationActivity.this);
							List<Address> address;

							String mLocality = "";
							String mThoroughfare = "";

							try {

								if (respStr.indexOf(tagOpenLat) != -1) {
									int startLocLat = respStr.indexOf(tagOpenLat) + tagOpenLat.length();
									int endLocLat = respStr.indexOf(tagCloseLat);
									String valueLocLat = respStr.substring(startLocLat, endLocLat);

									if (respStr.indexOf(tagOpenLat) != -1) {
										int startLocLon = respStr.indexOf(tagOpenLng) + tagOpenLng.length();
										int endLocLon = respStr.indexOf(tagCloseLng);
										String valueLocLon = respStr.substring(startLocLon, endLocLon);

										address = coder.getFromLocation((double) (Double.parseDouble(valueLocLat)),
												(double) (Double.parseDouble(valueLocLon)), 1);
										if (address == null || address.size() == 0) {
										} else {
											final Address location = address.get(0);
											if (location.getThoroughfare() != null) {
												mThoroughfare = location.getThoroughfare();
											}
											if (location.getLocality() != null) {
												if (mThoroughfare.equals("")) {
													mLocality = location.getLocality();
												} else {
													mLocality = " - " + location.getLocality();
												}
											}
										}
									}
								}
							} catch (Exception e) {
								e.printStackTrace();
							} finally {

								final GeoPoint p = new GeoPoint((int) (longitude * 1E6), (int) (latitude * 1E6));

								// first overlay
								final Drawable drawable = getResources().getDrawable(R.drawable.flag_export);
								final CustomItemizedOverlay<CustomOverlayItem> itemizedOverlay = new CustomItemizedOverlay<CustomOverlayItem>(
										drawable, mMapView);

								String title = mThoroughfare + mLocality;

								CustomOverlayItem overlayItem = new CustomOverlayItem(p,
										title.equals("") ? getStringAltimeterMetersFeets() : title,
										title.equals("") ? "" : getStringAltimeterMetersFeets(), null);
								itemizedOverlay.addOverlay(overlayItem);
								try {
									itemizedOverlay.onBalloonTap(0, overlayItem);
								} catch (Exception e) {
								}

								mMapView.getOverlays().add(itemizedOverlay);
								mMapController.animateTo(p);
								if (mMapView.getZoomLevel() < 8) {
									mMapController.setZoom(8);
								}
								mMapView.invalidate();
								hideProgressAsync();

							}

						}
						try {
							instream.close();
						} catch (IOException e) {
							e.printStackTrace();
						}
					}
				});
			}
		} catch (ClientProtocolException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			hideProgressAsync();
		}

	}

	private void getElevationFromGoogleMapsMod(double longitude, double latitude) {
		showProgressAsync();

		HttpClient httpClient = new DefaultHttpClient();
		HttpContext localContext = new BasicHttpContext();
		String url = "http://maps.googleapis.com/maps/api/elevation/" + "xml?locations=" + String.valueOf(longitude)
				+ "," + String.valueOf(latitude) + "&sensor=true";
		HttpGet httpGet = new HttpGet(url);
		try {
			HttpResponse response = httpClient.execute(httpGet, localContext);
			HttpEntity entity = response.getEntity();
			if (entity != null) {
				InputStream instream = entity.getContent();
				int r = -1;
				StringBuffer respStr = new StringBuffer();
				while ((r = instream.read()) != -1)
					respStr.append((char) r);
				String tagOpen = "<elevation>";
				String tagClose = "</elevation>";
				if (respStr.indexOf(tagOpen) != -1) {
					int start = respStr.indexOf(tagOpen) + tagOpen.length();
					int end = respStr.indexOf(tagClose);
					String value = respStr.substring(start, end);
					resultMeters = (double) (Double.parseDouble(value));
					resultFeet = (double) (Double.parseDouble(value) * 3.2808399);

					mHandler.post(new Runnable() {
						public void run() {
							if (!ShareUtils.getInstance().shareFacebook(
									ElevationActivity.this,
									getString(R.string.fb_msg)
											+ " "
											+ String.valueOf(resultMeters).substring(0,
													String.valueOf(resultMeters).indexOf(".") + 2)
											+ " "
											+ getString(R.string.meters)
											+ " | "
											+ String.valueOf(resultFeet).substring(0,
													String.valueOf(resultFeet).indexOf(".") + 2) + " "
											+ getString(R.string.feets))) {
								hideProgressAsync();
								AlertDialog.Builder builder;
								builder = new AlertDialog.Builder(ElevationActivity.this);
								builder.setTitle(R.string.warning).setIcon(android.R.drawable.ic_dialog_alert)
										.setMessage(getString(R.string.facebook_share_error))
										.setPositiveButton("Ok", new DialogInterface.OnClickListener() {

											public void onClick(DialogInterface dialog, int which) {
											}

										}).create().show();
							}
						}
					});

				}
				instream.close();
			}
		} catch (ClientProtocolException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			hideProgressAsync();
		}

	}

	@Override
	protected boolean isRouteDisplayed() {
		return false;
	}

	private void drawIcon() {
		showProgressAsync();

		if (mLocation != null) {

			Thread t = new Thread(new Runnable() {

				@Override
				public void run() {
					getElevationFromGoogleMaps(mLocation.getLatitude(), mLocation.getLongitude());
				}
			});
			t.start();

		}
		hideProgressAsync();

	}

	private String getStringAltimeterMetersFeets() {
		return String.valueOf(resultMeters).substring(0, String.valueOf(resultMeters).indexOf(".") + 2) + " "
				+ getString(R.string.meters) + " | "
				+ String.valueOf(resultFeet).substring(0, String.valueOf(resultFeet).indexOf(".") + 2) + " "
				+ getString(R.string.feets);
	}

	@Override
	protected void onResume() {
		if (mFirstStart && mLocation == null) {
			if (mLocationManager.isProviderEnabled(LocationManager.GPS_PROVIDER) && !mResume) {
				mResume = true;
				setupLocationManager(false);
			} else if (mLocationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER) && !mResume) {

				ConnectivityManager conMan = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);

				// mobile
				State mobile = conMan.getNetworkInfo(ConnectivityManager.TYPE_MOBILE).getState();

				// wifi
				State wifi = conMan.getNetworkInfo(ConnectivityManager.TYPE_WIFI).getState();

				if (mobile == NetworkInfo.State.CONNECTED || mobile == NetworkInfo.State.CONNECTING
						|| wifi == NetworkInfo.State.CONNECTED || wifi == NetworkInfo.State.CONNECTING) {
					mResume = true;
					networkListener();
				} else {
					new AlertDialog.Builder(ElevationActivity.this).setIcon(android.R.drawable.ic_dialog_alert)
							.setTitle(R.string.warning).setMessage(R.string.check_network)
							.setPositiveButton("Ok", new DialogInterface.OnClickListener() {

								@Override
								public void onClick(DialogInterface dialog, int which) {
								}

							}).show();
				}
			}
		} else {
			mFirstStart = true;
		}
		super.onResume();
	}

	private void networkListener() {
		if (mLocationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER)) {
			showProgressAsync();
			mLocationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 0, 0, mLocationListenerNetwork);
			mHandler.post(new Runnable() {

				public void run() {
					new CountDownTimer(10000, 1000) {

						public void onTick(long millisUntilFinished) {
						}

						public void onFinish() {
							try {
								mLocation = mLocationManager.getLastKnownLocation(LocationManager.NETWORK_PROVIDER);
								mLocationManager.removeUpdates(mLocationListenerNetwork);
								drawIcon();
								hideProgressAsync();
							} catch (Exception e) {
								hideProgressAsync();
							}
						}
					};
				}
			});
		} else {
			mLocation = mLocationManager.getLastKnownLocation(LocationManager.NETWORK_PROVIDER);
			drawIcon();
		}
	}

	public boolean onCreateOptionsMenu(Menu menu) {
		super.onCreateOptionsMenu(menu);
		MenuInflater oMenu = getMenuInflater();
		oMenu.inflate(R.layout.menu, menu);

		mSatView = menu.findItem(R.id.mapSat);
		mStreetView = menu.findItem(R.id.mapStreet);

		if (mMapView.isSatellite()) {
			mSatView.setVisible(false);
		} else {
			mStreetView.setVisible(false);
		}
		return true;
	}

	public boolean onOptionsItemSelected(MenuItem item) {
		switch (item.getItemId()) {
		case R.id.mapStreet:
			mMapView.setSatellite(false);
			mMapView.invalidate();
			mSatView.setVisible(true);
			mStreetView.setVisible(false);
			return true;

		case R.id.mapSat:
			mMapView.setSatellite(true);
			mMapView.invalidate();
			mSatView.setVisible(false);
			mStreetView.setVisible(true);
			return true;
		}
		return false;
	}
}